package com.rongmei.jdsync.util;

import org.apache.commons.io.FilenameUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.UUID;

/**
 * @author dongjun
 */
@Component
public class MediaDownloader {
    private static final Logger logger = LoggerFactory.getLogger(MediaDownloader.class);

    // 默认超时时间(毫秒)
    private static final int TIMEOUT = 30000;
    // 缓冲区大小
    private static final int BUFFER_SIZE = 8192;
    // 最大重试次数
    private static final int MAX_RETRY = 3;


    /**
     * 从指定URL下载媒体文件并保存到指定目录。
     *
     * @param mediaUrl 媒体文件的URL地址
     * @param saveDir  保存文件的目录路径
     * @param fileName 文件名，如果为null，则自动生成文件名
     * @return 下载的文件的路径
     * @throws IOException 如果在下载过程中发生I/O错误
     */
    public static String downloadMediaFromUrl(String mediaUrl, String saveDir, String fileName) throws IOException {
        validateUrl(mediaUrl);

        // 确定文件类型和保存目录
        String fileType = getFileType(mediaUrl);
        // 创建保存目录
        Files.createDirectories(Paths.get(saveDir));

        // 生成文件名
        String filePath = Paths.get(saveDir, fileName).toString();

        return downloadWithRetry(mediaUrl, filePath, fileType);
    }

    /**
     * 使用重试机制下载文件
     *
     * @param url      要下载的文件URL
     * @param filePath 文件下载后保存的本地路径
     * @param fileType 文件类型
     * @return 文件保存路径
     * @throws IOException 如果下载过程中发生I/O异常
     */
    private static String downloadWithRetry(String url, String filePath, String fileType) throws IOException {
        int retryCount = 0;
        IOException lastException = null;

        while (retryCount < MAX_RETRY) {
            try {
                HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
                connection.setRequestMethod("GET");
                connection.setConnectTimeout(TIMEOUT);
                connection.setReadTimeout(TIMEOUT);

                try (BufferedInputStream in = new BufferedInputStream(connection.getInputStream()); FileOutputStream out = new FileOutputStream(filePath)) {

                    byte[] buffer = new byte[BUFFER_SIZE];
                    int bytesRead;
                    while ((bytesRead = in.read(buffer)) != -1) {
                        out.write(buffer, 0, bytesRead);
                    }

                    logger.info("成功下载{}文件: {} -> {}", fileType, url, filePath);
                    return filePath;
                }
            } catch (IOException e) {
                lastException = e;
                logger.warn("下载失败(尝试{}): {}", retryCount + 1, e.getMessage());
                retryCount++;
                new File(filePath).delete();

                if (retryCount < MAX_RETRY) {
                    try {
                        Thread.sleep(1000L * retryCount);
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                    }
                }
            }
        }

        throw new IOException("下载失败，重试" + MAX_RETRY + "次后仍不成功", lastException);
    }

    /**
     * 验证给定的URL是否有效。
     *
     * @param url 要验证的URL字符串
     * @throws IllegalArgumentException 如果URL为空、包含空白字符或协议不是http/https，则抛出此异常
     */
    private static void validateUrl(String url) {
        if (url == null || url.trim().isEmpty()) {
            throw new IllegalArgumentException("URL不能为空");
        }
        if (!url.startsWith("http")) {
            throw new IllegalArgumentException("不支持的URL协议: " + url);
        }
    }

    /**
     * 根据给定的URL获取文件类型
     *
     * @param url 文件的URL地址
     * @return 返回文件的类型，根据文件扩展名返回"images"或"videos"，如果无法判断则默认返回"images"
     */
    private static String getFileType(String url) {
        // 首先尝试从URL获取扩展名
        String extension = FilenameUtils.getExtension(url).toLowerCase();
        if (extension.matches("(jpg|jpeg|png|gif|webp|bmp)")) {
            return "images";
        } else if (extension.matches("(mp4|mov|avi|mkv|flv|wmv)")) {
            return "videos";
        }

        // 如果URL没有扩展名或无法识别，默认返回null，将在下载时检查Content-Type
        return null;
    }

    /**
     * 生成文件名
     *
     * @param url      输入的文件URL
     * @param fileType 文件类型，如 "images" 或 "videos"
     * @return 生成的文件名
     */
    private static String generateFileName(String url, String fileType, String contentType) {
        String extension = FilenameUtils.getExtension(url);

        // 如果URL没有扩展名，尝试从Content-Type获取
        if (extension.isEmpty() && contentType != null) {
            if (contentType.startsWith("image/")) {
                extension = contentType.substring(6); // 获取"image/"之后的部分
            } else if (contentType.startsWith("video/")) {
                extension = contentType.substring(6); // 获取"video/"之后的部分
            }
        }

        // 如果仍然无法确定扩展名，根据文件类型设置默认值
        if (extension.isEmpty()) {
            extension = "images".equals(fileType) ? "jpg" : "mp4";
        }

        // 清理扩展名中的特殊字符
        extension = extension.replaceAll("[^a-zA-Z0-9]", "");

        return UUID.randomUUID() + "." + extension;
    }

    // 示例用法
//    public static void main(String[] args) {
//        try {
//            String imageUrl = "https://img30.360buyimg.com/sku/jfs/t1/236080/32/17560/97811/66311efaF94a1996b/ea1cfec64e3bfc22.png";
//            String savePath = downloadMediaFromUrl(imageUrl, , "1122");
//            System.out.println("文件保存路径: " + savePath);
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//    }
}
